package com.ticket.sass.admin.util;

import com.google.gson.*;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Type;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

public class GsonUtil {
    private static final Gson GSON = buildGson();
    
    private GsonUtil() {
        // 私有构造函数，防止实例化
    }
    
    public static Gson getInstance() {
        return GSON;
    }
    
    private static Gson buildGson() {
        Set<String> sensitiveFields = new HashSet<>();
        // 添加敏感字段的名称
        sensitiveFields.add("password");
        sensitiveFields.add("newPassword");
        sensitiveFields.add("p12File");
        sensitiveFields.add("file");
        sensitiveFields.add("response");
        
        return new GsonBuilder()
            .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter())
            .registerTypeAdapter(LocalDate.class, new LocalDateAdapter())
            .setExclusionStrategies(new SensitiveFieldExclusionStrategy(sensitiveFields))
            .setExclusionStrategies(new MultipartFileExclusionStrategy())
            .setDateFormat("yyyy-MM-dd'T'HH:mm:ss") // 设置日期格式
            .create();
    }
    
    
    // 自定义排除策略
    static class MultipartFileExclusionStrategy implements ExclusionStrategy {
        @Override
        public boolean shouldSkipField(FieldAttributes f) {
            // 忽略 MultipartFile 类型的字段
            return f.getDeclaredType() == MultipartFile.class;
        }
        
        @Override
        public boolean shouldSkipClass(Class<?> clazz) {
            return false;
        }
    }
    
    // 自定义排除策略
    static class SensitiveFieldExclusionStrategy implements ExclusionStrategy {
        private final Set<String> sensitiveFields;
        
        public SensitiveFieldExclusionStrategy(Set<String> sensitiveFields) {
            this.sensitiveFields = sensitiveFields;
        }
        
        @Override
        public boolean shouldSkipField(FieldAttributes f) {
            // 忽略敏感字段
            return sensitiveFields.contains(f.getName());
        }
        
        @Override
        public boolean shouldSkipClass(Class<?> clazz) {
            return false;
        }
    }
    
    
    private static class LocalDateTimeAdapter implements JsonSerializer<LocalDateTime>,
        JsonDeserializer<LocalDateTime> {
        
        private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
        
        @Override
        public JsonPrimitive serialize(LocalDateTime src, Type typeOfSrc, com.google.gson.JsonSerializationContext context) {
            return new JsonPrimitive(formatter.format(src));
        }
        
        @Override
        public LocalDateTime deserialize(com.google.gson.JsonElement json, Type typeOfT, com.google.gson.JsonDeserializationContext context) {
            return LocalDateTime.parse(json.getAsString(), formatter);
        }
    }
    
    private static class LocalDateAdapter implements JsonSerializer<LocalDate>,
        JsonDeserializer<LocalDate> {
        
        private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        
        @Override
        public JsonPrimitive serialize(LocalDate src, Type typeOfSrc, com.google.gson.JsonSerializationContext context) {
            return new JsonPrimitive(formatter.format(src));
        }
        
        @Override
        public LocalDate deserialize(com.google.gson.JsonElement json, Type typeOfT, com.google.gson.JsonDeserializationContext context) {
            return LocalDate.parse(json.getAsString(), formatter);
        }
    }
    
    public static String toJsonString(Object obj){
        if (Objects.isNull(obj)){
            return "{}";
        }
        
        return GSON.toJson(obj);
    }
}
